from typing import Literal, Union, Optional, List
from pydantic import BaseModel, Field
from .chat_completion_function import OpenaiFunctionCall
from .chat_completion_tool import OpenaiChatCompletionMessageToolCallParam

__all__ = [
    "OpenaiChatCompletionMessage",
    "OpenaiChatCompletionContentPartParam",
    "OpenaiChatCompletionContentPartTextParam",
    "OpenaiChatCompletionContentPartImageParam",
    "OpenaiChatCompletionSystemMessageParam",
    "OpenaiChatCompletionUserMessageParam",
    "OpenaiChatCompletionAssistantMessageParam",
    "OpenaiChatCompletionToolMessageParam",
    "OpenaiChatCompletionFunctionMessageParam",
    "OpenaiImageURL",
]


class OpenaiImageURL(BaseModel):
    url: str = Field(..., description="Either a URL of the image or the base64 encoded image data.")

    detail: Literal["auto", "low", "high"] = Field(
        description="Specifies the detail level of the image. Learn more in the Vision guide."
    )


class OpenaiChatCompletionContentPartImageParam(BaseModel):
    image_url: OpenaiImageURL = Field(...)

    type: Literal["image_url"] = Field(..., description="The type of the content part.")


class OpenaiChatCompletionContentPartTextParam(BaseModel):
    text: str = Field(..., description="The text content.")

    type: Literal["text"] = Field(..., description="The type of the content part.")


OpenaiChatCompletionContentPartParam = Union[
    OpenaiChatCompletionContentPartTextParam, OpenaiChatCompletionContentPartImageParam
]


class OpenaiChatCompletionSystemMessageParam(BaseModel):
    content: str = Field(..., description="The contents of the system message.")

    role: Literal["system"] = Field(..., description="The role of the messages author, in this case system.")

    name: str = Field(
        default=None,
        description="An optional name for the participant. Provides the model information to differentiate between participants of the same role.",
    )


class OpenaiChatCompletionUserMessageParam(BaseModel):
    content: Union[str, List[OpenaiChatCompletionContentPartParam]] = Field(
        ..., description="The contents of the user message."
    )

    role: Literal["user"] = Field(..., description="The role of the messages author, in this case user.")

    name: str = Field(
        None,
        description="An optional name for the participant. Provides the model information to differentiate between participants of the same role.",
    )


class OpenaiChatCompletionAssistantMessageParam(BaseModel):
    role: Literal["assistant"] = Field(..., description="The role of the message's author, in this case assistant.")

    content: Optional[str] = Field(
        None,
        description="The contents of the assistant message. Required unless tool_calls or function_call is specified.",
    )

    function_call: Optional[OpenaiFunctionCall] = Field(
        None,
        description="Deprecated and replaced by tool_calls. The name and arguments of a function that should be called, as generated by the model.",
    )

    name: Optional[str] = Field(
        None,
        description="An optional name for the participant. Provides the model information to differentiate between participants of the same role.",
    )

    tool_calls: Optional[List[OpenaiChatCompletionMessageToolCallParam]] = Field(
        None, description="The tool calls generated by the model, such as function calls."
    )


class OpenaiChatCompletionToolMessageParam(BaseModel):
    content: str = Field(..., description="The contents of the tool message.")

    role: Literal["tool"] = Field(..., description="The role of the messages author, in this case tool.")

    tool_call_id: str = Field(..., description="Tool call that this message is responding to.")


class OpenaiChatCompletionFunctionMessageParam(BaseModel):
    content: Optional[str] = Field(..., description="The contents of the function message.")

    name: str = Field(..., description="The name of the function to call.")

    role: Literal["function"] = Field(..., description="The role of the messages author, in this case function.")


OpenaiChatCompletionMessage = Union[
    OpenaiChatCompletionAssistantMessageParam,
    OpenaiChatCompletionToolMessageParam,
    OpenaiChatCompletionFunctionMessageParam,
    OpenaiChatCompletionUserMessageParam,
    OpenaiChatCompletionSystemMessageParam,
]
